Produire une carte à partir d’un jeu de données trouvé en ligne est désormais une opération assez simple. Quelques lignes de code peuvent peuvent suffire, comme le montre l’exemple ci-dessous mettant à profit un jeu de données sur les crimes commis sur le territoire montréalais (l’importation du jeu de données peut prendre plusieurs secondes, selon la vitesse de votre connexion internet) :
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
library(mapview)# Importation d'un fichier comportant les coordonnées géographiques de crimes commis à Montréal# Élimination à la volée des données non pourvues de coordonnées, puis sélection aléatoire d'un échantillon de 500 observationsgeo <-geojson_sf("https://data.montreal.ca/dataset/5829b5b0-ea6f-476f-be94-bc2b8797769a/resource/aacc4576-97b3-4d8d-883d-22bbca41dbe6/download/actes-criminels.geojson") |>filter(!is.na(LONGITUDE)) |>slice_sample(n=500)# Création de la carte avec le jeu de données importémapview(geo["CATEGORIE"])
On arrive, avec très peu de moyens, à produire grâce à l’extension mapview une carte interactive d’une très grande qualité.
Il faut dire que R possède des extensions de grande qualité développées, soutenues et utilisées par les géographes. Si vous possédez un jeu de données qui comporte les coordonnées géographiques d’objets du monde réel et que ce jeu répond aux standards Simple Feature Access (SF), le passage vers la représentation cartographique sera pratiquement un jeu d’enfant. Vous trouverez en ligne quantité de cours et de tutoriels qui vous montreront à utiliser les fonctions de l’une ou l’autre des extentions spécialisées.
L’objectif de l’atelier n’est pas d’ajouter à cette documentation abondante. Plutôt, il vise à faire le pont entre l’analyse des données textuelles et les extensions spécialisées. Même si l’exercice débouchera, deux fois plutôt qu’une, sur la création de cartes géographiques, on veut prendre le problème en amont de l’exercice cartographique en proposant une chaîne de traitement possible pour passer des données textuelles aux cartes géographiques.
Objectifs:
repérer dans des textes des objets du monde réel qui puissent être géolocalisés (sous forme de polygones et sous forme de points), puis extraire les chaînes de caractères représentant ces objets;
obtenir par croisement de tables et par API (tidygeocoder) les coordonnées géographiques de ces objets;
projeter les résultats sur des carte.
Nous allons essayer d’atteindre ces objectifs à travers deux tâches plus précises.
Première tâche
La première tâche consistera à extraire de textes de fictions les noms de quartiers de Montréal et à projeter ensuite sur une carte géographique ces mêmes quartiers sous forme de polygones. Une échelle de couleurs sera établie pour traduire la fréquence d’apparition des noms de quartiers dans l’ensemble du corpus.
Deuxième tâche
La deuxième tâche consistera à extraire du même corpus les mentions des universités montréalaises, à géoréférencer ces universitiés avec tidygeocoder, puis à projeter sur une carte géographique les points correspondant à ces objets.
Installation et activation des extensions
Il convient d’abord de préparer l’environnement de travail. La fonction ci-dessous permet d’importer dans l’environnement des extensions si elles ne le sont pas déjà, puis de les activer.
#| echo: false# Création d'une fonction d'installation et d'activation des extensionsinst_ext_fun <-function(extension) {if(!extension %in%rownames(installed.packages())) {install.packages(extension, dependencies =TRUE) }require(extension, character.only =TRUE) }# usageextensions <-c("ggplot2","leaflet","leaflet.extras","data.table","tidygeocoder","sf","dplyr","stringi","stringr","tmap","tmaptools","viridis","geojsonsf","mapview" )# Application de la fonction à chaque élément du vecteur `extensions`sapply(extensions, inst_ext_fun)
Loading required package: ggplot2
Loading required package: leaflet
Loading required package: leaflet.extras
Loading required package: data.table
Attaching package: 'data.table'
The following objects are masked from 'package:dplyr':
between, first, last
Loading required package: tidygeocoder
Loading required package: sf
Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is TRUE
Le jeu de données que nous allons utiliser est celui qui a été exploré dans les précédents ateliers. Il s’agit d’un tableau de données (data frame) contenant 563 nouvelles littéraires publiées dans XYZ: la revue de la nouvelle entre 2012 et 2022. Les textes ont été moissonnés sur le site Érudit par Amélie Ducharme et Yu Chen Shi, sous la supervision de Julien Vallières-Gingras.
# Lecture du jeu de donnéesxyz <- data.table::fread("donnees/donnees_importees/xyz.csv")# Observer la structurestr(xyz)
Classes 'data.table' and 'data.frame': 563 obs. of 7 variables:
$ Titre : chr "Le labyrinthe" "Échoueries" "Old Harry" "Atshen" ...
$ Auteur: chr "Louise Dupré" "Claire Legendre" "Marie-Andrée Arsenault" "Charles Sagalane" ...
$ Numéro: chr "149" "149" "149" "149" ...
$ Date : chr "printemps 2022" "printemps 2022" "printemps 2022" "printemps 2022" ...
$ Thème : chr "Îles : l’archipel des solitudes" "Îles : l’archipel des solitudes" "Îles : l’archipel des solitudes" "Îles : l’archipel des solitudes" ...
$ URI : chr "https://id.erudit.org/iderudit/97693ac" "https://id.erudit.org/iderudit/97694ac" "https://id.erudit.org/iderudit/97695ac" "https://id.erudit.org/iderudit/97696ac" ...
$ Texte : chr "Le traversier accosterait dans vingt minutes environ, une femme venait de le mentionner en anglais à une autre "| __truncated__ "Ça aurait été l’histoire d’une écrivaine triste partie dépenser ce qu’il lui restait d’argent dans l’archipel d"| __truncated__ "Ses mains portaient les entailles profondes que font les filins au bout desquels se débattent les lourds poisso"| __truncated__ "Supposez que nous soyons à cinquante mille lunes d’ici. Je ne parle pas de distance, mais bien de l’astre qui a"| __truncated__ ...
- attr(*, ".internal.selfref")=<externalptr>
# Il n'y a pas d'identifiant unique. On peut en composer en utilisant, dans les URL moissonnés, les séquences numériques uniques.xyz$doc_id <-as.integer(str_sub( xyz$URI, start =-7L, end =-3L ) )# Vérifier que les doc_id sont uniquestable(!duplicated(xyz$doc_id))
TRUE
563
# Observer à nouveau la structurestr(xyz)
Classes 'data.table' and 'data.frame': 563 obs. of 8 variables:
$ Titre : chr "Le labyrinthe" "Échoueries" "Old Harry" "Atshen" ...
$ Auteur: chr "Louise Dupré" "Claire Legendre" "Marie-Andrée Arsenault" "Charles Sagalane" ...
$ Numéro: chr "149" "149" "149" "149" ...
$ Date : chr "printemps 2022" "printemps 2022" "printemps 2022" "printemps 2022" ...
$ Thème : chr "Îles : l’archipel des solitudes" "Îles : l’archipel des solitudes" "Îles : l’archipel des solitudes" "Îles : l’archipel des solitudes" ...
$ URI : chr "https://id.erudit.org/iderudit/97693ac" "https://id.erudit.org/iderudit/97694ac" "https://id.erudit.org/iderudit/97695ac" "https://id.erudit.org/iderudit/97696ac" ...
$ Texte : chr "Le traversier accosterait dans vingt minutes environ, une femme venait de le mentionner en anglais à une autre "| __truncated__ "Ça aurait été l’histoire d’une écrivaine triste partie dépenser ce qu’il lui restait d’argent dans l’archipel d"| __truncated__ "Ses mains portaient les entailles profondes que font les filins au bout desquels se débattent les lourds poisso"| __truncated__ "Supposez que nous soyons à cinquante mille lunes d’ici. Je ne parle pas de distance, mais bien de l’astre qui a"| __truncated__ ...
$ doc_id: int 97693 97694 97695 97696 97697 97698 97699 97700 97701 97703 ...
- attr(*, ".internal.selfref")=<externalptr>
# La variable "Date" contient l'année. On peut extraire cette information et l'emmagasiner dans une nouvelle colonnexyz$annee <-as.integer(str_extract(string = xyz$Date, pattern ="[0-9]+"))## Exercice: créez une table montrant la distribution des numéros par année# table()# Faire le même exercice avec la variable `numéro`. Que remarquez-vous?table(xyz$Numéro)
# Il faut d'abord extraire les nombres (irrégularité dans l'entrée de données)# L'argument `pattern` est une expression régulière. Pourriez-vous l'expliquer?xyz$Numéro <-as.integer(str_extract(xyz$Numéro, pattern ="[0-9]{1,3}"))# Essayer à nouveautable(xyz$Numéro)
# Hourra!# Donner des noms adéquats aux colonnescolnames(xyz) <-c("titre","auteur","numero","Date","theme","url","texte","doc_id", "annee")# Allègement de la structure de donnéesxyz <- xyz[, c("doc_id", "titre", "auteur", "numero", "annee", "theme", "texte")]# str(xyz)# Exporter cette table# fwrite(xyz, "donnees/donnees_produites/csv/combined_table_net_xyz.csv")
Première tâche
Les quartiers montréalais comme objets géographiques
Les données géographiques
Pour que des lieux physiques puissent être transposés sur une carte géographique, il faut en proposer une représentation qui respecte un ensemble de normes. La norme Simple Feature Access est celle que les spécialistes suivent dans la construction, le stockage et le traitement des objets pourvus d’attributs géographiques.
Dans R, l’extension sf implémente cette norme Simple Feature Access (ou simplement SF). Ce qu’on appelle feature peut être conçu comme un objet du monde réel: un immeuble, une place publique, une ville, un cours d’eau, une forêt, une chaîne de montagnes. Une ville par exemple, selon la perspective (le point dans l’espace depuis lequel on la considère), sera représentée par un point, un polygone ou un ensemble de polygones (si elle est traversée par des cours d’eau). Une rivière prendra généralement la forme d’une série de points formant une ligne brisée, et ainsi de suite. Les points, les polygones, les multipolygones et les lignes sont les principales formes avec lesquels on représente les objets sur une carte. Un objet géoréférencé aura d’autres attributs (exemple: population, température moyenne, altitude, etc.). Toutes ces données, géographiques et autres, seront emmagasinées selon la norme SF dans un tableau de données, une structure comportant deux dimensions (avec lignes et colonnes).
Dans le bloc suivant, nous allons importer un fichier avec une extension .shp (shapefile). Il a été récupéré sur le site de Données Québec et contient les données géographiques des quartiers sociologiques de Montréal. Nous allons supprimer certaines colonnes sans intérêt immédiat, puis y ajouter une nouvelle colonne appelée regex (pour “expression régulière”). Ces expressions régulières permettront ensuite d’associer les noms de quartiers trouvés dans les textes du corpus à des noms de quartier standardisés.
# Importation d'une table comprenant les noms de quartiers et les coordonnées correspondant à leurs délimitationsquartiersGeoMtl <- sf::read_sf("donnees/donnees_importees/quartiers_sociologiques_2014/quartiers_sociologiques_2014.shp" )# print(quartiersGeoMtl)# str(quartiersGeoMtl)# Sélection des colonnes d'intérêtquartiersGeoMtl <- quartiersGeoMtl[, c("Q_socio", "Abrev", "geometry")]# Observation de cette structure de donnéesstr(quartiersGeoMtl)
sf [32 × 3] (S3: sf/tbl_df/tbl/data.frame)
$ Q_socio : chr [1:32] "Ahuntsic" "Bordeaux-Cartierville" "Anjou" "Côte-des-Neiges" ...
$ Abrev : chr [1:32] "AHU" "AHU" "AJ" "CDN" ...
$ geometry:sfc_MULTIPOLYGON of length 32; first list element: List of 1
..$ :List of 1
.. ..$ : num [1:564, 1:2] 289315 289329 289366 289385 289420 ...
..- attr(*, "class")= chr [1:3] "XY" "MULTIPOLYGON" "sfg"
- attr(*, "sf_column")= chr "geometry"
- attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA
..- attr(*, "names")= chr [1:2] "Q_socio" "Abrev"
# Ajout d'une colonne avec 32 expressions régulières, une pour chaque nom de quartier.quartiersGeoMtl$regex <-c("[Aa]huntsic","[Bb]ordeaux.[Cc]artierville","[Aa]njou","([Cc][ôo]te.des.[Nn]eiges)|(cdn|CDN)","([Nn]otre.[Dd]ame.de[Gg]r[aâ]ce)|(NDG|ndg\b)","[Nn]ord.[Oo]uest.{1,14}[Mm]ontréal","[Ll]achine","[Ll]a[Ss]alle","[Hh]ochelag","[Mm]ercier.[Oo]uest","[Mm]ercier.[Ee]uest","[Mm]ontréal.[Nn]ord","[Oo]tremont","([Pp]lateau.[Mm]ont.[Rr]oyal)|le Plateau","[Pp]ointe.aux.[Tt]rembles","[Rr]ivière.des.[Pp]rairies","[Pp]etite.[Pp]atrie","[Rr]osemont","[Vv]ille.[Ss]aint.[Ll]aurent","[Ss]aint.[Ll]éonard","[Pp]etite.[Bb]ourgogne","([Pp]ointe.[Ss]aint.[Cc]arles)|(\bpsc\b|PSC)","[Ss]aint.[Hh]enri","([Vv]ille.[EÉée]mard|[Cc][ôo]te.[Ss]aint.[Pp]aul)","[Vv]erdun","[Cc]entre.[Ss]ud","[Ff]aubourg.[Ss]aint.[Ll]aurent","([Pp]eter|[Qq]artier).[Mm]c.?[Gg]ill","[Vv]ieux.[Mm]ontréal","[Pp]arc.[Ee]xtension","[Ss]aint.[Mm]ichel","[Vv]illeray")# On peut faire un test d'indexation avec avec Côte-des-Neiges (4e expression régulière)# xyz[texte %like% quartiersGeoMtl$regex[4]]
Extraction des noms de quartiers dans les textes
Les expressions régulières permettront de repérer sinon la totalité, du moins le plus grand nombre de mention des noms de quartiers dans les textes du corpus. Ces expressions seront d’abord transformées en un seul long vecteur, chaque expression étant séparée des autres par l’opérateur | (équivalent de “ou”). Le vecteur sera ensuite projeté dans les textes du corpus et attrapera, pour ainsi dire, les noms de quartiers. Chaque fois qu’un texte comprendra une chaîne de caractères répondant aux critères de l’expression, cette chaine sera extraite du texte et placée dans une nouvelle colonne appelée quartiers_nommes.
# Première étape: créer une seule et longue regex avec celles de la colonne du même nomregex_tous_quartiers <-paste(quartiersGeoMtl$regex, sep ="", collapse ="|")# Extraction des noms avec cette expression régulière. Les chaînes ainsi extraites seront placées dans une nouvelle colonne appelée "quartiers_nommes".xyz$quartiers_nommes <-sapply(xyz$texte, str_extract_all, pattern = regex_tous_quartiers)# str(xyz)# Élimination des doublonsxyz$quartiers_nommes <-sapply(xyz$quartiers_nommes, unique)# L'opération d'extraction a généré des listes. # On peut assembler les éléments de ces listes avec `paste()`xyz$quartiers_nommes <-sapply(xyz$quartiers_nommes, paste, collapse ="; ")# Vérification du succès de l'opérationxyz[quartiers_nommes !="", .(quartiers_nommes)]
# Conversion des chaines extraites des textes en noms officiels xyz$quartiers_nommes <-stri_replace_all_regex( xyz$quartiers_nommes,pattern = quartiersGeoMtl$regex,replacement = quartiersGeoMtl$Q_socio,vectorize =FALSE )
Constitution d’une table pour visualisation
Nous avons maintenant deux tables à notre disposition. La première contient les textes et les métadonnées, ainsi qu’une colonne où sont indiqués les quartiers nommés dans les textes. La deuxième est un un objet de type SF et contient ces mêmes noms de quartiers associés à des coordonnées géographiques. Pour passer à la prochaine étape, soit la projection de la fréquence des mentions de quartiers dans une carte géographique, nous devons créer une troisième table qui contiendra trois informations: le nom du quartier, le nombre de fois que ce quartier est mentionné dans l’ensemble du corpus, et les données géographiques de ces quartiers.
# Création d'une liste comprenant tous les noms de quartiersquartiers_nommes_sep_l <-strsplit(xyz$quartiers_nommes, "; ")# Élimination des éléments sans contenuvaleurs_non_nulles <-which(quartiers_nommes_sep_l !="character(0)")quartiers_nommes_sep_l <- quartiers_nommes_sep_l[valeurs_non_nulles]# Extraction des noms emmagasinés dans la liste et transfert de ces noms dans un tableau de donnéesquartiers_empiles <-data.table(Q_socio =c(sapply(quartiers_nommes_sep_l, "[", 1),sapply(quartiers_nommes_sep_l, "[", 2),sapply(quartiers_nommes_sep_l, "[", 3),sapply(quartiers_nommes_sep_l, "[", 4) ))# Calcul de la fréquence des noms de quartiersfreq_quartiers <- quartiers_empiles[!is.na(Q_socio) , .N, "Q_socio"]# En base R, la même opération serait faite comme suit:# quartiers_empiles_sansNA <- quartiers_empiles[!is.na(quartiers_empiles$Q_socio),]# freq_quartiers_df <- data.frame(Q_socio = names(table(quartiers_empiles_sansNA)),# N = unname(as.integer(table(quartiers_empiles_sansNA))))# On joint maintenant la table de fréquence et celle contenant les coordonnées géographiquesfreq_quartiers_geo <-left_join( quartiersGeoMtl[, c("Q_socio", "Abrev", "geometry")], freq_quartiers, by ="Q_socio" )# Cette opération a introduit dans la table de fréquence des noms de quartiers qui n'y étaient pas et dont la fréquence est NA. Nous allons transformer ces NA en 0.freq_quartiers_geo$N <-ifelse(is.na(freq_quartiers_geo$N),0, freq_quartiers_geo$N )
Les graphiques
Comme n’importe quel jeu de données, celui que nous avons créé peut être observé sous la forme d’un diagramme de dispersion ou à points.
Un tel diagramme ne tire cependant pas parti des données géographiques du tableau. L’extension ggplot2 qu’on vient d’utiliser pour créer le diagramme de dispersion permet d’ajouter une couche graphique. La fonction prend en entrée l’objet sf et repère automatiquement la colonne geo contenant les coordonnées de polygones.
Dans la suite de l’atelier, on utilisera plutôt des extensions spécialisées.
Projection des dimensions dans l’espace géographique
Plusieurs extensions permettent d’utiliser les données géographiques pour produire des cartes statiques et interactives. Leaflet et tmap sont parmi les plus utilisées. D’autres, comme mapview, s’appuient sur leaflet et simplifient le processus. Vous trouverez en ligne une documentation abondante et plusieurs exemples avec divers jeux de données
L’extension tmap
L’extension tmap fonctionne sur le principe de la grammaire des graphiques dont il a été question dans le précédent atelier sur ggplot2. On fournit à la fonction d’entrée tm_shape() un jeu de données et on ajoute ensuite des couches pour ajuster les formes et autres éléments tels les titres, symboles, légendes, etc.
tmap_mode("plot")
tmap mode set to plotting
# Fonction de base, à laquelle on ajoute les polygonestm_shape(freq_quartiers_geo) +tm_fill(col ="N", palette ="viridis") +tm_layout(legend.height =0.5)
# Avec des tranchestm_shape(freq_quartiers_geo) +tm_polygons(col ="N", breaks =c(0,3,5), palette ="viridis") +tm_layout(legend.height =0.5)
# Avec algorithme (jenks = identification des groupes similaires)tm_shape(freq_quartiers_geo) +tm_polygons(col ="N", style ="jenks", palette ="viridis") +tm_layout(legend.height =0.5)
# Avec une seule couleur par catégorietm_shape(freq_quartiers_geo) +tm_polygons(col ="N", style ="cat", palette ="viridis") +tm_layout(legend.height =0.5)
# Ajout de composantes graphiques (boussole, titres, etc.)freq_shape <-tm_shape(freq_quartiers_geo) +tm_polygons(col ="N", style ="cat", palette ="viridis") +tm_layout(legend.height =0.5)# Ajout d'une boussolefreq_shape +tm_compass(type ="8star", position =c("left", "top"))
# Ajout d'un titrefreq_shape +tm_layout(title ="Quartiers montréalais dans les nouvelles\nde la revue XYZ")
# Taille des élémentsfreq_shape +tm_layout(title ="Quartiers montréalais dans les nouvelles\nde la revue XYZ", title.size =0.8)
# Couleur de l'arrière-planfreq_shape +tm_layout(title ="Quartiers montréalais dans les nouvelles\nde la revue XYZ", title.size =0.8, bg.color ="grey85")
# Élimination du cadrefreq_shape +tm_layout(title ="Quartiers montréalais dans les nouvelles\nde la revue XYZ", title.size =0.8, frame =FALSE)
# Ajout d'un titre et des crédits, puis déplacement de la légendefreq_shape +tm_layout(title ="Quartiers montréalais dans les nouvelles\nde la revue XYZ", scale =0.7, frame =FALSE) +tm_credits("Source des données: XYZ", position =c("right", "BOTTOM"))
# Utilisation d'une feuille de stylestm_shape(freq_quartiers_geo) +tm_polygons(col ="N") +tm_style("bw")
# Ajout des abréviations de quartiers (ici, on aurait pu conserver et utiliser les codes de quartiers pour éviter les superpositions)tm_shape(freq_quartiers_geo) +tm_polygons(col ="N") +tm_style("col_blind") +tm_text("Abrev", size =0.4)
Deuxième tâche
Nous allons maintenant composer un vecteur comprenant quatre expressions régulières. Elles seront utilisées pour extraire des textes les noms des universités montréalaises.
# Expressions régulières unies en une seule chaîne de caractèresregex_univ <-c("université.de.montréal|\\bu\\.?de?\\.?m\\.?\\b|université.du.québec.à.montréal|\\buq[aà]m\\b|concordia|mcgill")# Extraction des nomsxyz[, univ_nommees:=str_extract_all(tolower(texte), regex_univ)]# Remplacement des character(0) par NA dans la nouvelle colonne du tableauxyz$univ_nommees <-lapply(xyz$univ_nommees, function(x) if(identical(x, character(0))) ""else x)# Élimination des doublonsxyz[, univ_nommees:=lapply(univ_nommees, unique)]# L'opération d'extraction a généré des listes. # On peut assembler les éléments de ces listes avec `paste()`xyz$univ_nommees <-sapply(xyz$univ_nommees, function(x) paste(x, collapse ="; "))# Vérification de l'opérationxyz[univ_nommees !="", .(univ_nommees)]
univ_nommees
1: université de montréal
2: université de montréal
3: uqam
4: université de montréal
5: uqam; concordia
6: mcgill
7: uqam; université de montréal
8: université de montréal
9: mcgill
10: université de montréal
# Les noms étant uniformes et "propres", nous n'aurons pas besoin de les normaliser comme on l'a fait pour les noms de quartiers.
Création d’une table de fréquence avec les entités géographiques
# Création d'une liste comprenant tous les noms de quartiersuniv_nommees_sep_l <-strsplit(xyz$univ_nommees, "; ")# Élimination des éléments sans contenuvaleurs_non_nulles <-which(univ_nommees_sep_l !="character(0)")univ_nommees_sep_l <- univ_nommees_sep_l[valeurs_non_nulles]# On vérifie le nombre maximal de valeurs uniques dans chaque textemax(sapply(univ_nommees_sep_l, length))
[1] 2
# Transposition des données dans un tableauuniv_empilees <-data.table(nom_univ =c(sapply(univ_nommees_sep_l, "[", 1),sapply(univ_nommees_sep_l, "[", 2) ))# Table de fréquencesfreq_univ <- univ_empilees[!is.na(nom_univ) , .N, "nom_univ"][order(N, decreasing =TRUE) ]# Pour faciliter le géoréférencement, nous allons ajouter une colonne avec l'adresse de chaque institutionfreq_univ$adresse <-c("3150, rue Jean-Brillant, Montreal, Quebec, Canada","1430, rue Saint-Denis, Montreal, Quebec, Canada","845, rue Sherbrooke Ouest, Montreal, Quebec, Canada","1455, boulevard de Maisonneuve Ouest, Montreal, Quebec, Canada")
Travailler avec Tidygeocoder
Nous sommes maintenant prêts à géoréférencer nos données. Les adresses seront passées à la fonction geocode() de l’extension tidygeocoder. Celle-ci traduit nos requêtes, écrites en langage R, dans un format que l’API puisse interpréter (normalement json). La réponse de l’API, une fois reçue par tidygeocoder, est transformée en un tableau de données de type tibble. Si vos adresses ne sont pas déjà intégrées à un tableau de données, vous pouvez les passer sous la forme d’un vecteur à la fonction tidygeocoder::geo(). Essayez par exemple avec une adresse que vous connaissez bien.
# Exercice: remplacer l'adresse dans l'instruction ci-dessous par une adresse de votre choix, puis observez le résultat.mon_adresse <-geo(address ="1000, rue de la Gauchetière, Montréal, Québec, Canada")
Passing 1 address to the Nominatim single address geocoder
Query completed in: 1 seconds
Comme nos adresses sont dans un tableau de données, nous allons utiliser la fonction geocode(). Nous allons ensuite transformer le tableau de données en un objet de type Simple Feature.
Passing 4 addresses to the Nominatim single address geocoder
Query completed in: 4 seconds
# Transformation du tableau de données en objet Simple Featurefreq_univ_geo_sf <-st_as_sf(freq_univ_geo, coords =c("long", "lat"), crs =st_crs(4326))# Création d'une colonne avec des abréviationsfreq_univ_geo_sf$Abrev <-c("UdeM", "UQAM", "McGill", "Concordia")# Si le géoréférencement échoue, vous pouvez exécuter l'instruction ci-dessous# freq_univ_geo_sf <- readRDS("donnees/donnees_produites/rds/freq_univ_geo_sf.RDS")
Les coordonnées du polygone de l’île de Montréal pourront nous être utilisées pour créer une couche sur laquelle les points seront déposés.
# Importation des coordonnées à partir du site de la Ville de Montréalmtl_poly <-geojson_sf("https://data.montreal.ca/dataset/b628f1da-9dc3-4bb1-9875-1470f891afb1/resource/92cb062a-11be-4222-9ea5-867e7e64c5ff/download/limites-terrestres.geojson")# Observation rapide de la formemtl_poly |>mapview()
Nous sommes maintenant prêts à projeter les points sur un plan géographique. Nous utiliserons la fonction tm_bubbles(), qui permet d’adapter le volume des points à une variable numérique (notre variable N):
tmap_mode("plot")
tmap mode set to plotting
tm_shape(mtl_poly) +tm_polygons() +tm_shape(freq_univ_geo_sf) +tm_bubbles(size ="N", col ="red")
tmap_mode("view")
tmap mode set to interactive viewing
tm_shape(mtl_poly) +tm_polygons() +tm_shape(freq_univ_geo_sf) +tm_bubbles(size ="N", col ="red")
Legend for symbol sizes not available in view mode.
# Le mode "view" permet d'utiliser des couches de base variées:tmap_mode("view")
tmap mode set to interactive viewing
# Modification de paramètrestm_basemap(server ="Stamen.Toner") +tm_shape(mtl_poly) +tm_polygons(col="white", border.col ="blue") +tm_shape(freq_univ_geo_sf) +tm_bubbles(size ="N", col ="red", scale =3)
Legend for symbol sizes not available in view mode.
# Le mode "plot" permet de d'ajouter d'autres éléments visuelstmap_mode("plot")
tmap mode set to plotting
tm_shape(mtl_poly) +tm_polygons(col="white", border.col ="blue") +tm_shape(freq_univ_geo_sf) +tm_bubbles(size ="N", col ="red", scale =3)+tm_text(text ="Abrev", size =0.5)+tm_credits("Source des données: Revue XYZ") +tm_layout(main.title ="Universités montréalaises dans\nles nouvelles de la revue XYZ",fontface ="bold",title.size =0.5)
# Fonction de sauvegardemtl_univ_plot <-tm_shape(mtl_poly) +tm_polygons(col="white", border.col ="blue") +tm_shape(freq_univ_geo_sf) +tm_bubbles(size ="N", col ="red", scale =3)+tm_text(text ="nom_univ", size =0.5)+tm_credits("Source des données: Revue XYZ") +tm_layout(main.title ="Universités montréalaises dans\nles nouvelles de la revue XYZ",fontface ="bold",title.size =0.5)tmap_save(tm = mtl_univ_plot,filename ="donnees/donnees_produites/graphiques/mtl_univ_plot.png")
Map saved to /Users/pascalbrissette/github/PERSONNEL/Ateliers/20230406_PB_atelier_ladirec_geo/donnees/donnees_produites/graphiques/mtl_univ_plot.png
Resolution: 2263.864 by 1947.997 pixels
Size: 7.546214 by 6.493322 inches (300 dpi)
# Exercice:# Modifiez l'échelle et la couleur des bulles# Modifiez les modes de visualisation ("plot", "view")# La fonction `tm_basemap()` permet d'importer des toiles de fond variées. Remplacez "Stamen.Toner" par "Stamen.Watercolor" ou "Esri.WorldImagery". D'autres options sont proposées https://leaflet-extras.github.io/leaflet-providers/preview/
Pour aller plus loin
Jesse Cambon, Diego Hernangomez, Christopher Belanger, Daniel Possenriede, “Tidygeocoder: An R package for geocoding”, 2021. DOI: https://doi.org/10.21105/joss.03544